<?php
/**
 * appRain v 0.1.x
 *
 * LICENSE
 *
 * This source file is subject to the MIT license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://www.opensource.org/licenses/mit-license.php
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@apprain.com so we can send you a copy immediately.
 *
 * @copyright  Copyright (c) 2010 appRain, Team. (http://www.apprain.com)
 * @license    http://www.opensource.org/licenses/mit-license.php MIT license
 *
 * HELP
 *
 * Official Website
 * http://www.apprain.com/
 *
 * Download Link
 * http://www.apprain.com/download
 *
 * Documents Link
 * http ://www.apprain.com/docs
 */

abstract class appRain_Base_Modules_search extends appRain_Base_Objects
{
    public $searchPool = Array();
    const LINK_RELATIVE = 'Relative';
    const LINK_ABSOLUTE = 'Absolute';
    const CACHE_PRE_FIX = '__search__';
    const PARMA_DESC_LEANGTH = 200;

    public function search($srt = "")
    {
        if( $srt == "" ) return "";

        $this->setSearchString($srt);

        if(!$this->hasCache())
        {
            $this->searchPool = Array();

            App::__obj("Development_Callbacks")->_before_search_init($this);

            foreach(App::__def()->getCategorySetList() as $name )
            {
                $srcStr = $this->CategorySetSearchData($name);
                if(!empty($srcStr))
                {
                    $this->searchPool = array_merge($this->searchPool,$srcStr);
                }
            }

            foreach(App::__def()->getInformationSetList() as $type )
            {
                $srcStr = $this->getSearchableFields($type);
                if(!empty($srcStr))
                {
                    $this->searchPool = array_merge($this->searchPool,$this->processInformationSet($type,$srcStr));
                }
            }

            App::__obj("Development_Callbacks")->_after_search_init($this);

            $this->createCache();
        }
        else
        {
            $this->searchPool = $this->readCache();
        }

        return App::Helper('Utility')->array_paginator($this->searchPool,Array('limit'=>$this->getLimit(),'h_link'=>$this->getHLink(),'page'=>$this->getPage(),'smart'=>$this->getSmartPaging()));
    }

    private function readCache()
    {
        if(app::__def()->sysConfig('SEARCH_CACHE') == 'File')  return App::Module('Cache')->Read($this->cacheKey());
        else if(app::__def()->sysConfig('SEARCH_CACHE') == 'Session') return App::Module('Session')->Read($this->cacheKey());
    }

    private function createCache()
    {
        if(!empty($this->searchPool))
        {
            if(app::__def()->sysConfig('SEARCH_CACHE') == 'File')  App::Module('Cache')->Write($this->cacheKey(),$this->searchPool);
            else if(app::__def()->sysConfig('SEARCH_CACHE') == 'Session') App::Module('Session')->Write($this->cacheKey(),$this->searchPool);
        }

        return $this;
    }

    private function hasCache()
    {
        if(app::__def()->sysConfig('SEARCH_CACHE') == 'NoCache') return false;
        else if(app::__def()->sysConfig('SEARCH_CACHE') == 'File') return App::Module('Cache')->exists($this->cacheKey());
        else if(app::__def()->sysConfig('SEARCH_CACHE') == 'Session'){return App::Module('Session')->exists($this->cacheKey());}
    }

    private function cacheKey()
    {
        return self::CACHE_PRE_FIX . App::Helper('Utility')->text2Normalize($this->getSearchString());
    }

    private function categorySetSearchData($name)
    {
        $definition = App::__def()->getCategorySetDefinition($name);
        $definition['search']['status'] = isset($definition['search']['status']) ? $definition['search']['status'] : "No";
        $srcstr = $this->getSearchString();

        $data = Array();
        if( $definition['search']['status'] == 'Yes')
        {
            $tmp = App::CategorySet($name)->findAll("title LIKE '%{$srcstr}%' OR description LIKE '%{$srcstr}%'");

            foreach($tmp['data'] as $key => $val)
            {
                $uri = str_replace('[id]',$val['id'],$definition['search']['parma-link']['uri']);
                $uri = str_replace('[title]',App::Helper('Utility')->text2Normalize($val[$definition['search']['field-selected']]),$uri);

                if(ucfirst($definition['search']['parma-link']['type']) ==  self::LINK_ABSOLUTE)
                {
                    $val['_parmalink'] = App::Helper('Html')->linkTag($uri,$val[$definition['search']['field-selected']]);
                }
                else
                {
                    $val['_parmalink'] = App::Helper('Html')->linkTag(App::Helper('Config')->baseurl("/{$uri}"),$val[$definition['search']['field-selected']]);
                }

                $val['_parmadesc'] = substr($val['description'],0,self::PARMA_DESC_LEANGTH);
                $data[] = $val;
            }
        }
        return $data;
    }

    private function processInformationSet($type=null, $srcStr=null)
    {
        $definition = App::__def()->getInformationSetDefinition($type);

        $result = App::InformationSet($type)->FindAll($srcStr);

        $data = Array();
        foreach($result['data'] as $val)
        {
            $uri = $definition['base']['search']['parma-link']['uri'];

            foreach(explode("/",$uri) as $needle)
            {
                if( substr($needle,0,1) == "[" && (substr($needle,(strlen($needle)-1),(strlen($needle)))) == "]")
                {
                    $field = substr($needle,1,strlen($needle)-2);
                    $uri = str_replace($needle,$val[$field],$uri);
                }
            }

            if(ucfirst($definition['base']['search']['parma-link']['type']) ==  self::LINK_ABSOLUTE)
            {
                $val['_parmalink'] = App::Helper('Html')->linkTag($uri,$val[$definition['base']['search']['field-selected']]);
            }
            else
            {
                $val['_parmalink'] = App::Helper('Html')->linkTag(App::Helper('Config')->baseurl("/{$uri}"),$val[$definition['base']['search']['field-selected']]);
            }

            $val['_parmadesc'] = isset($val[$definition['base']['search']['field-description']]) ? substr($val[$definition['base']['search']['field-description']],0,self::PARMA_DESC_LEANGTH) : "";

            $data[] = $val;
        }
        return $data;
    }

    private function getSearchableFields($type)
    {
        $definition = App::__def()->getInformationSetDefinition($type);

        $srcStr = Array();
        $definition['base']['search']['status'] = isset($definition['base']['search']['status']) ? $definition['base']['search']['status'] : "No";
        if(strtolower($definition['base']['search']['status']) == 'yes')
        {
            $i = 0;
            foreach($definition['fields'] as $name => $field)
            {
                if(strtolower($field['searchable']) == 'yes')
                {
                    if(!empty($srcStr))
                    {
                        if($i%2 == 0)
                        {
                            $srcStr[] = 'OR';
                        }
                    }

                    $srcStr[] = Array($name=>'%' . $this->getSearchString() . '%',"cnd"=>"LIKE");
                }
            }
        }
        return $srcStr;
    }
}